home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -in_the_mag- / multitasking / coders / setf / setf.e < prev    next >
Text File  |  2000-03-05  |  3KB  |  108 lines

  1. /* setf.e -- a SnoopDos-like program to monitor calls to OpenLibrary() */
  2.  
  3. OPT OSVERSION=37
  4.  
  5. MODULE 'dos/dos', 'exec/ports', 'exec/tasks', 'exec/nodes', 'exec/memory'
  6.  
  7. CONST OFFSET=$fdd8  /* execbase offset of OpenLibrary() */
  8.  
  9. /* "mymsg" must begin with the standard message object "mn", followed by
  10.    any kind of data (in this case, two pointers [to strings]).
  11. */
  12. OBJECT mymsg
  13.   msg:mn
  14.   s, t
  15. ENDOBJECT
  16.  
  17. /* "port" will be used from the patched routine, too, so it's global */
  18. DEF port:PTR TO mp
  19.  
  20. /* You can change the library function to be patched by changing OFFSET
  21.    and the "execbase" in the *two* calls to SetFunction().  If you want to
  22.    patch a library other than dos, exec, graphics and intuition you need
  23.    to OpenLibrary() it first.
  24.    (Note: some [old?] libraries cannot be patched in this way.  Also, some
  25.    functions in some libraries can't be patched like this either!  Even the
  26.    RKRM's aren't too clear about this...)
  27. */
  28. PROC main()
  29.   DEF ps, us, loop, sig, oldf
  30.   IF port:=CreateMsgPort()
  31.     Forbid()     /* Don't let anyone mess things up... */
  32.     IF oldf:=SetFunction(execbase, OFFSET, {newf})
  33.       PutLong({patch}, oldf)
  34.       Permit()    /* Now we can let everyone else back in */
  35.       LEA store(PC), A0
  36.       MOVE.L A4, (A0)    /* Store the A4 register... */
  37.       ps:=Shl(1,port.sigbit)   /* Set up port and user signal bits */
  38.       us:=SIGBREAKF_CTRL_C
  39.       loop:=TRUE
  40.       WHILE loop
  41.         sig:=Wait(ps OR us)
  42.         IF sig AND ps
  43.           printmsgs()
  44.         ENDIF
  45.         IF sig AND us
  46.           loop:=FALSE
  47.         ENDIF
  48.       ENDWHILE
  49.       Forbid()   /* Paranoid... */
  50.       SetFunction(execbase, OFFSET, oldf)
  51.     ENDIF
  52.     Permit()
  53.     printmsgs()   /* Make sure the port is empty */
  54.     DeleteMsgPort(port)
  55.   ENDIF
  56. ENDPROC
  57.  
  58. /* Nicely (?) print the messages out... */
  59. PROC printmsgs()
  60.   DEF msg:PTR TO mymsg
  61.   WHILE msg:=GetMsg(port)
  62.     WriteF('Task \l\s[25] wants \r\s[20]\n',
  63.            IF msg.t THEN msg.t ELSE '*unnamed*',
  64.            IF msg.s THEN msg.s ELSE '*unnamed library*')
  65.     ReplyMsg(msg)
  66.     DisposeLink(msg.s)
  67.     DisposeLink(msg.t)
  68.     Dispose(msg)
  69.   ENDWHILE
  70. ENDPROC
  71.  
  72. /* Send a message to the patching process */
  73. PROC sendmsg()
  74.   DEF m:PTR TO mymsg, s, tsk:tc, l:ln
  75.   MOVE.L A1, s
  76.   /* Allocate a new message */
  77.   m:=New(SIZEOF mymsg)
  78.   IF s
  79.     m.s:=String(StrLen(s))
  80.     StrCopy(m.s,s,ALL)
  81.   ENDIF
  82.   tsk:=FindTask(NIL)   /* Find out who we are */
  83.   m.t:=NIL
  84.   IF tsk
  85.     l:=tsk.ln
  86.     IF l AND l.name
  87.       m.t:=String(StrLen(l.name))
  88.       StrCopy(m.t, l.name, ALL)
  89.     ENDIF
  90.   ENDIF
  91.   PutMsg(port, m)
  92. ENDPROC
  93.  
  94. /* Place to store A4 register */
  95. store:  LONG 0
  96. /* Place to store real call */
  97. patch:  LONG 0
  98.  
  99. /* The new routine which will replace the original library function */
  100. newf:
  101.   MOVEM.L D0-D7/A0-A6, -(A7)
  102.   LEA store(PC), A0
  103.   MOVE.L (A0), A4 /* Reinstate the A4 register so we can use E code */
  104.   sendmsg()
  105.   MOVEM.L (A7)+, D0-D7/A0-A6
  106.   MOVE.L patch(PC), -(A7)
  107.   RTS
  108.